package penguin.rpc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import penguin.common.Constants;
import penguin.transfer.dto.TransferDTO;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 1 连接注册中心
 * 2 向注册中心传 projectName ip port remoteNameList
 * 3 注册中心返回 remoteNameList 对应的 ip port
 * 4.每一个 remoteName 获取一个 ip 进行连接，如果连接中断 remove掉这个ip 则换一个ip继续连接
 * 5.每30秒一次和服务中心心跳 从注册中心发过来一次 remoteNameList 对应的ip host
 * 6.如果和服务中心心跳断掉 则尝试 每1秒一次重连，无限循环（以后更改为添加备用地址，即注册中心支持多台）
 *
 * Created on 15/7/8 下午10:10
 *
 * @author 王建华(penguin83@126.com)
 */
public class RegisterClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(RegisterClient.class);

    private String projectName;
    private List<String> registerAddressList;
    private RpcServer rpcServer;
    private RpcClient registerRpcClient;
    private String currentAddress;  //host:port

    private Map<String,RpcClient> remoteProjectClientMap = new HashMap<String, RpcClient>();

    private ScheduledExecutorService scheduledExecutorService;

    public  void init(){

        LOGGER.debug("开始连接注册中心");

        //1.连接注册中心
        this.registerRpcClient =  new RpcClient();
        this.registerRpcClient.setAddressList(registerAddressList);
        this.registerRpcClient.initDirect();
        LOGGER.debug("注册中心连接成功");

        //启动 周期性心跳
        scheduledExecutorService = Executors.newScheduledThreadPool(1);
        scheduledExecutorService.scheduleWithFixedDelay(new RegisterHeartBeat(), 0, Constants.HEART_TIME_REIGSTER, TimeUnit.MILLISECONDS);
    }

    public void registerRemoteProject(String remoteProjectName, RpcClient rpcClient) {
        remoteProjectClientMap.put(remoteProjectName, rpcClient);
    }

    public RpcServer getRpcServer() {
        return rpcServer;
    }

    public void setRpcServer(RpcServer rpcServer) {
        this.rpcServer = rpcServer;
    }

    public String getProjectName() {

        return projectName;
    }

    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }

    public String getCurrentAddress() {
        return currentAddress;
    }

    public void setCurrentAddress(String currentAddress) {
        this.currentAddress = currentAddress;
    }

    public List<String> getRegisterAddressList() {
        return registerAddressList;
    }

    public void setRegisterAddressList(List<String> registerAddressList) {
        this.registerAddressList = registerAddressList;
    }

    class RegisterHeartBeat implements  Runnable{

        @Override
        public void run() {

            String localHost = "error";
            try {
                localHost =  InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
            }

            Set<String> remoteProjectSet = remoteProjectClientMap.keySet();
            Map<String,List<String>> remoteProjectAddressMap = null;
            try {
                remoteProjectAddressMap = (Map<String,List<String>>)registerRpcClient.execSync("registerService","getProjectAddressMap",projectName,localHost,rpcServer.getPort(),remoteProjectSet);
            } catch (Exception e) {
                LOGGER.error("RegisterHeartBeat error",e);
                return;
            }

            if(remoteProjectAddressMap == null ){
                return;
            }

            for(String projectName:remoteProjectSet){

                List<String> addressList = remoteProjectAddressMap.get(projectName);
                RpcClient rpcClient = remoteProjectClientMap.get(projectName);
                rpcClient.setAddressList(addressList);
                rpcClient.connect();
            }
        }
    }

}
